package avicit.bdp.dms.tdm.service;

import avicit.bdp.common.base.BaseService;
import avicit.bdp.common.utils.BdpLogUtil;
import avicit.bdp.common.utils.DateUtils;
import avicit.bdp.core.constant.Constants;
import avicit.bdp.dms.tdm.dao.AssetLogDao;
import avicit.bdp.dms.tdm.dto.AssetLogDTO;
import avicit.bdp.dms.tdm.utils.ApplyServiceType;
import avicit.bdp.dms.tdm.utils.CheckerStatus;
import avicit.bdp.dms.tdm.utils.ResourceType;
import avicit.bdp.dms.tdm.utils.SysOrgUtils;
import avicit.platform6.api.syslookup.dto.SysLookupSimpleVo;
import avicit.platform6.api.system.ConvertColumnClient;
import avicit.platform6.api.system.SysLookupClient;
import avicit.platform6.api.system.impl.SystemConstant;
import avicit.platform6.commons.utils.BusinessUtil;
import avicit.platform6.commons.utils.ComUtil;
import avicit.platform6.commons.utils.PojoUtil;
import avicit.platform6.core.context.ThreadContextHelper;
import avicit.platform6.core.exception.DaoException;
import avicit.platform6.core.properties.PlatformConstant;
import avicit.platform6.core.rest.msg.QueryRespBean;
import avicit.platform6.modules.system.syslog.service.SysLogUtil;
import com.alibaba.fastjson2.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @金航数码科技有限责任公司
 * @作者：${tableInfo.classCreator}
 * @邮箱：${tableInfo.classMailbox}
 * @创建时间： 2023-11-14 16:03
 * @类说明：bdp_asset_logService
 * @修改记录：
 */
@Service
public class AssetLogService extends BaseService<AssetLogDao, AssetLogDTO> {

    private static final Logger logger = LoggerFactory.getLogger(AssetLogService.class);

    @Autowired
    private AssetLogDao assetLogDao;
    @Autowired
    private SysOrgUtils sysOrgUtils;
    @Autowired
    private ConvertColumnClient convertColumnClient;
    @Autowired
    SysLookupClient sysLookupClient;
    @Autowired
    private AssetPortalService assetPortalService;
    @Autowired
    private BdpAssetService assetService;

    /**
     * 分页查询资产使用日志
     *
     * @param assetId
     * @param pageNo
     * @param pageSize
     * @return
     * @throws Exception
     */
    public QueryRespBean<AssetLogDTO> getAssetLogPageList(String assetId, String callUserId, Integer pageNo, Integer pageSize)
            throws Exception {
        QueryRespBean<AssetLogDTO> queryRespBean = new QueryRespBean<>();
        PageHelper.startPage(pageNo, pageSize);
        Page<AssetLogDTO> pageList = assetLogDao.getAssetLogPageList(assetId, callUserId);
        valueConvert(pageList.getResult());
        queryRespBean.setResult(pageList);
        BdpLogUtil.log4Query(queryRespBean);
        return queryRespBean;
    }

    /**
     * 新增对象
     *
     * @param dto 保存对象
     * @return String
     */
    @Transactional
    public String save(AssetLogDTO dto) {
        try {
            dto.setId(ComUtil.getId());
            PojoUtil.setSysProperties(dto, PlatformConstant.OpType.insert);
            this.insert(dto);
            // 记录日志
            SysLogUtil.log4Insert(dto);
            return dto.getId();
        } catch (Exception e) {
            throw new DaoException(e.getMessage(), e);
        }
    }

    /**
     * 通过主键查询单条记录
     *
     * @param id 主键id
     */
    @Transactional(readOnly = true)
    public AssetLogDTO queryById(String id) {
        try {
            AssetLogDTO dto = this.selectByPrimaryKey(id);
            // 记录日志
            if (dto != null) {
                SysLogUtil.log4Query(dto);
            }
            return dto;
        } catch (Exception e) {
            throw new DaoException(e.getMessage(), e);
        }
    }

    /**
     * 内部方法，获取修改的dto对象
     *
     * @param dto
     * @return
     */
    private AssetLogDTO getUpdateDto(AssetLogDTO dto) {
        AssetLogDTO oldDTO = this.selectByPrimaryKey(dto.getId());
        if (oldDTO == null) {
            throw new DaoException("数据不存在");
        }
        //记录日志
        SysLogUtil.log4Update(dto, oldDTO);
        PojoUtil.setSysProperties(dto, PlatformConstant.OpType.update);
        PojoUtil.copyProperties(oldDTO, dto, true);
        return oldDTO;
    }

    /**
     * 资产监控概览
     *
     * @return
     */
    @Transactional(readOnly = true)
    public Map<String, Object> overview(String timeType) {
        logger.info("时间类型:{}", timeType);
        Map<String, Object> map = new HashMap<>();
        // 资产类型分布数据
        Map<String, Integer> assetTypeMap = new HashMap<>();
        assetTypeMap.put("1", 1);
        assetTypeMap.put("2", 2);
        assetTypeMap.put("3", 3);
        assetTypeMap.put("4", 4);
        //String orgId = ThreadContextHelper.getOrgId();
        //根据时间类型获取开始时间和结束时间
        Map<String,Object> timeMap = this.handleTime(timeType);
        String beginTime = MapUtils.getString(timeMap,"beginTime","");
        String endTime = MapUtils.getString(timeMap,"endTime","");
        List<Map<String, Object>> list = assetLogDao.getAssetTypeCount(beginTime, endTime);
        List<JSONObject> assetTypeCountList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(list)) {
            for (Map<String, Object> item : list) {
                String assetType = (String) item.get("asset_type");
                Long num = (Long) item.get("num");
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("name", ResourceType.getDescByCode(Integer.valueOf(assetType)));
                jsonObject.put("value", num);
                assetTypeCountList.add(jsonObject);

                if (assetTypeMap.containsKey(assetType)) {
                    assetTypeMap.remove(assetType);
                }
            }
        }
        if (assetTypeMap.size() > 0) {
            Set<String> set = assetTypeMap.keySet();
            Iterator<String> it = set.iterator();
            while (it.hasNext()) {
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("name", ResourceType.getDescByCode(Integer.valueOf(it.next())));
                jsonObject.put("value", 0);
                assetTypeCountList.add(jsonObject);
            }
        }
        map.put("assetTypeCountList", assetTypeCountList);

        // 资产总数
        long assetNum = assetLogDao.countAssetNum(beginTime, endTime);
        map.put("assetNum", assetNum);

        // 申请总数
        long assetApplyNum = assetLogDao.countAssetApplyNum(beginTime, endTime);
        map.put("assetApplyNum", assetApplyNum);

        // 访问次数
        long assetLogNum = assetLogDao.countAssetLogNum(beginTime, endTime);
        map.put("assetLogNum", assetLogNum);

        // 资产申请信息
        Map<Integer, Integer> checkerStatusMap = new HashMap<>();
        checkerStatusMap.put(1, 1);
        checkerStatusMap.put(2, 2);
        checkerStatusMap.put(3, 3);
        checkerStatusMap.put(4, 4);

        //List<Map<String, Object>> applyStatusList = assetLogDao.getApplyStatusCount(timeType, orgId);
        List<Map<String, Object>> applyStatusList = assetLogDao.getApplyStatusCount(beginTime, endTime);
        List<JSONObject> applyStatusCountList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(applyStatusList)) {
            for (Map<String, Object> item : applyStatusList) {
                Integer checkerStatus = (Integer) item.get("checker_status");
                Long num = (Long) item.get("num");
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("name", CheckerStatus.getDescByCode(checkerStatus));
                jsonObject.put("value", num);
                applyStatusCountList.add(jsonObject);

                if (checkerStatusMap.containsKey(checkerStatus)) {
                    checkerStatusMap.remove(checkerStatus);
                }
            }
        }
        if (checkerStatusMap.size() > 0) {
            Set<Integer> set = checkerStatusMap.keySet();
            Iterator<Integer> it = set.iterator();
            while (it.hasNext()) {
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("name", CheckerStatus.getDescByCode(it.next()));
                jsonObject.put("value", 0);
                applyStatusCountList.add(jsonObject);
            }
        }
        map.put("applyStatusCountList", applyStatusCountList);

        // 访问量排行
        List<Map<String, Object>> top10LogList = assetLogDao.getTop10LogCount(beginTime, endTime);
        List<JSONObject> top10LogCountList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(top10LogList)) {
            for (Map<String, Object> item : top10LogList) {
                String releaseTitle = (String) item.get("release_title");
                Long num = (Long) item.get("num");
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("releaseTitle", releaseTitle);
                jsonObject.put("value", num);
                top10LogCountList.add(jsonObject);
            }
        }
        map.put("top10LogCountList", top10LogCountList);

        return map;
    }

    private Map<String, Object> handleTime(String timeType) {
        Map<String,Object> map = new HashMap<>();
        //格式化时间
        String beginTime = "";
        String endTime = "";
        Date today = new Date();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String todayString = dateFormat.format(today);
        if (StringUtils.isNotBlank(timeType) && "1".equals(timeType)){
            beginTime = todayString + " " + "00:00:00";
            endTime = todayString + " " + "23:59:59";
        } else if (StringUtils.isNotBlank(timeType) && "2".equals(timeType)) {
            String monday = DateUtils.getCurrentMonday(null);
            String sunday = DateUtils.getDayAfterToday(monday,6,null);
            beginTime = monday + " " + "00:00:00";
            endTime = sunday + " " + "23:59:59";
        } else if (StringUtils.isNotBlank(timeType) && "3".equals(timeType)){
            String currentMonth = DateUtils.getCurrentMonth();
            String first = DateUtils.getFirstDayOfMonth(currentMonth);
            Date lastDay = DateUtils.getLastDayOfMonth(new Date());
            String last = dateFormat.format(lastDay);
            beginTime = first + " " + "00:00:00";
            endTime = last + " " + "23:59:59";
        } else {
            String year = todayString.substring(0,4);
            beginTime = year + "-01-01 " + "00:00:00";
            endTime = year + "-12-31 " + "23:59:59";
        }
        map.put("beginTime",beginTime);
        map.put("endTime",endTime);
        return map;
    }

    /**
     * 通过平台API将字段值转换为名称，包括通用选择组件、通用代码
     *
     * @param assetLogList
     */
    private void valueConvert(List<AssetLogDTO> assetLogList) {
        //循环组装请求数据
        Map<String, Set<String>> convertFormData = new HashMap<>();
        for (AssetLogDTO assetLog : assetLogList) {
            BusinessUtil.createConvertSet(convertFormData, "BDP_DAM_APPLY_SERVICE_TYPE", String.valueOf(assetLog.getServiceType()));
            BusinessUtil.createConvertSet(convertFormData, SystemConstant.USER, assetLog.getCallUserId());
        }
        if (convertFormData.size() > 0) {
            //获取请求结果
            Map<String, Map<String, String>> convertResultData = convertColumnClient.replace(convertFormData);
            //循环设置Alias或Name的值
            for (AssetLogDTO assetLog : assetLogList) {
                assetLog.setServiceTypeName(BusinessUtil.convertFormat(convertResultData, "BDP_DAM_APPLY_SERVICE_TYPE", String.valueOf(assetLog.getServiceType())));
                assetLog.setCallUserName(BusinessUtil.convertFormat(convertResultData, SystemConstant.USER, assetLog.getCallUserId()));

                //申请单位—>根据申请人查询数据
                if (StringUtils.isNotEmpty(assetLog.getCallUserId())) {
                    assetLog.setApplyUnit(sysOrgUtils.getOrgByUserId(assetLog.getCallUserId()).getOrgName());
                }
            }
        }
    }

    public Map<String, Object> homeOverview() {
        Map<String, Object> map = new HashMap<>();
        //目录总数
        long categoryCount = this.mapper.countCategory();
        //资产数量
        long assetCount = this.mapper.countAsset();
        //服务次数
        //long accessCount = this.mapper.countAssetLogNum(null, null);
        Long accessCount = this.mapper.countAssetCallNum();
        if(accessCount == null){
            accessCount = Long.parseLong("0");
        }
        //接入系统数量
       /* List<String> datasourceIds = this.mapper.selectDatasourceIds();
        long datasourceCount = datasourceIds.size();*/
        Collection<SysLookupSimpleVo> lookupList = sysLookupClient.getLookUpListByTypeByAppIdNoFilter("BDP_DAM_ASSET_SOURCE", ThreadContextHelper.getAppId());
        long datasourceCount = lookupList.size();
        map.put("categoryCount", categoryCount);
        map.put("assetCount", assetCount);
        map.put("accessCount", accessCount);
        map.put("datasourceCount", datasourceCount);
        return map;
    }

    public List<Map<String, Object>> getAssetDatasources() {
        /*List<String> datasourceIds = this.mapper.selectDatasourceIds();
        if(CollectionUtils.isNotEmpty(datasourceIds)) {
            List<DataSourceDTO> list = dataSourceService.selectByIds(datasourceIds);
            return list;
        }
        return null;*/
        List list = Lists.newArrayList();
        Collection<SysLookupSimpleVo> lookupList = sysLookupClient.getLookUpListByTypeByAppIdNoFilter("BDP_DAM_ASSET_SOURCE", ThreadContextHelper.getAppId());
        for (SysLookupSimpleVo vo : lookupList) {
            Map<String, Object> map = new HashMap<>();
            map.put("sourceSystem", vo.getLookupCode());
            map.put("sourceSystemName", vo.getLookupName());
            list.add(map);
        }
        return list;
    }

    public List<Map<String, String>> homeCategorys() {
        return this.mapper.getHomeCategorys();
    }

    public void reportUrlLog(String assetId) {
        AssetLogDTO logDTO = assetPortalService.createAssetLog(assetId, ApplyServiceType.REPORT.getCode());
        try {
            logDTO.setCallStatus(1);
            logDTO.setCallResult("查询报表成功");
            //增加服务次数
            assetService.addCallCount(assetId);
        } catch (Exception e) {
            logDTO.setCallStatus(0);
            logDTO.setCallResult(e.getMessage());
            logger.error("查询报表异常", e);
            throw e;
        }

        logDTO.setEndTime(new Date());
        this.insert(logDTO);
    }
}